/**
 * Copyright (c) 2008 - TheNittyGritty - Thomas Brekelmans
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package nl.thenittygritty.utils 
{
	import flash.display.Graphics;	
	
	/**
	 * GraphicUtils is a library class which shouldn't be instantiated. 
	 * Instead it provides static methods which help in working with Graphics.
	 */
	public class GraphicsUtils 
	{
		/**
		 * Private constructor for the GraphicsUtils, this shouldn't be called.
		 */
		public function GraphicsUtils() 
		{
			// Throw an error, we shouldn't try to instantiate GraphicsUtils.
			throw new Error("The GraphicsUtils shouldn't be instantiated.");
		}
		
		/**
		 * Draws a rounded rectangle with support for a different radius for 
		 * each of the corners of the rectangle.
		 */
		public static function drawRoundRectComplex(graphics:Graphics, 
												x:Number, y:Number, 
												width:Number, height:Number, 
                              					topLeftRadius:Number, 
                              					topRightRadius:Number, 
                              					bottomLeftRadius:Number,
                              					bottomRightRadius:Number):void
		{
			var xw:Number = x + width;
			var yh:Number = y + height;

			// Make sure none of the radius values are greater than w/h.
			// These are all inlined to avoid function calling overhead
			var minSize:Number = width < height ? width * 2 : height * 2;
			topLeftRadius = topLeftRadius < minSize ? 
											topLeftRadius : minSize;
			topRightRadius = topRightRadius < minSize ? 
											  topRightRadius : minSize;
			bottomLeftRadius = bottomLeftRadius < minSize ? 
												  bottomLeftRadius : minSize;
			bottomRightRadius = bottomRightRadius < minSize ? 
													bottomRightRadius : minSize;
		
			// Math.sin and Math,tan values for optimal performance.
			// Math.rad = Math.PI / 180 = 0.0174532925199433
			// r * Math.sin(45 * Math.rad) =  (r * 0.707106781186547);
			// r * Math.tan(22.5 * Math.rad) = (r * 0.414213562373095);
			//
			// We can save further cycles by precalculating
			// 1.0 - 0.707106781186547 = 0.292893218813453 and
			// 1.0 - 0.414213562373095 = 0.585786437626905

			// bottom-right corner
			var a:Number = bottomRightRadius * 0.292893218813453;		
			// radius - anchor pt;
			var s:Number = bottomRightRadius * 0.585786437626905; 	
			// radius - control pt;
			graphics.moveTo(xw, yh - bottomRightRadius);
			graphics.curveTo(xw, yh - s, xw - a, yh - a);
			graphics.curveTo(xw - s, yh, xw - bottomRightRadius, yh);

			// bottom-left corner
			a = bottomLeftRadius * 0.292893218813453;
			s = bottomLeftRadius * 0.585786437626905;
			graphics.lineTo(x + bottomLeftRadius, yh);
			graphics.curveTo(x + s, yh, x + a, yh - a);
			graphics.curveTo(x, yh - s, x, yh - bottomLeftRadius);

			// top-left corner
			a = topLeftRadius * 0.292893218813453;
			s = topLeftRadius * 0.585786437626905;
			graphics.lineTo(x, y + topLeftRadius);
			graphics.curveTo(x, y + s, x + a, y + a);
			graphics.curveTo(x + s, y, x + topLeftRadius, y);

			// top-right corner
			a = topRightRadius * 0.292893218813453;
			s = topRightRadius * 0.585786437626905;
			graphics.lineTo(xw - topRightRadius, y);
			graphics.curveTo(xw - s, y, xw - a, y + a);
			graphics.curveTo(xw, y + s, xw, y + topRightRadius);
			graphics.lineTo(xw, yh - bottomRightRadius);
		}
	}
}
